package td;

import java.util.ArrayList;
import java.util.Random;

/*
 * Abstract parent class to store every information about enemies.
 * */
public abstract class Enemy extends FieldElement {
	protected int hp;
	protected float speed;
	public int value;
	protected int damage;
	protected DoTListener listener;
	public int slowduration;
	public int fireduration;
	public boolean slowed;
	public boolean onFire;
	public float slowlvl;
	public int fireDamage;

	public Enemy(Field position, DoTListener listener) {
		super(position);
		this.listener = listener;
		this.slowduration = 0;
		this.fireduration = 0;
		this.slowed = false;
		this.onFire = false;

	}

	public int getHp() {
		return this.hp;
	}

	public DoTListener getListener() {
		return this.listener;
	}

	/*
	 * Manages enemy death. Gives mana to player and removes enemy from the
	 * field.
	 */
	public void die() {
		listener.enemyDied(this);
		position.removeElement(this);
	}

	public abstract void step();

	/* Applies specific bullet damage to the enemy */
	public void getHurt(Bullet bullet) {
		if (bullet instanceof AoEBullet)
			getHurt((AoEBullet) bullet);
		else if (bullet instanceof SingleBullet)
			getHurt((SingleBullet) bullet);
		else if (bullet instanceof CutterBullet)
			getHurt((CutterBullet) bullet);
	}

	/*
	 * If it was a bullet with Area of Effect, it also damages every other
	 * enemies on the same field.
	 */
	public void getHurt(AoEBullet bullet) {
		SingleBullet aoe = new SingleBullet(bullet.damage, bullet.status);
		ArrayList<Enemy> fieldEnemies = position.getEnemies();
		for (int i = 0; i < fieldEnemies.size(); i++) {
			fieldEnemies.get(i).getHurt(aoe);
		}
		if (hp <= 0) {
			die();
		} else if (bullet.status == StatusEffects.DoT) {
			if (onFire == false) {
				fireduration = 2;
				fireDamage = 2;
				onFire = true;
				listener.enemyHasDoT(this);
			}
		}
		this.viewable.update();
	}

	/*
	 * If it was a cutter bullet, it calls the enemy's cutInHalf method, and
	 * also deals damage.
	 */
	public void getHurt(CutterBullet bullet) {
		hp -= bullet.damage;
		if (hp <= 0)
			die();
		else
			cutInHalf();
		this.viewable.update();
		this.position.viewable.update();
	}

	/*
	 * Method to test critical shots from ArcherTower in the game's prototype.
	 */
	public void getCriticalHurt(SingleBullet bullet) {
		hp -= (bullet.damage * 2);
		if (hp <= 0)
			die();
	}

	/*
	 * Method to apply damage of single targeted bullets. They can set enemies
	 * on fire, slow them down, or deal double damage if it was a critical.
	 */
	public void getHurt(SingleBullet bullet) {
		if (bullet.status != StatusEffects.None) {
			switch (bullet.status) {
			case DoT:
				hp -= bullet.damage;
				if (hp <= 0)
					die();
				else {
					if (onFire == false) {
						fireduration = 2;
						fireDamage = 2;
						onFire = true;
						listener.enemyHasDoT(this);
					}
				}
				break;
			case Slow:
				hp -= bullet.damage;
				if (hp <= 0)
					die();
				else {
					if (slowed) {
						slowduration = 2;
					} else {
						speed += 1;
						slowduration = 2;
						slowed = true;
						listener.enemyHasDoT(this);
					}
				}
				break;
			case Critical:
				Random rand = new Random();
				int crit = rand.nextInt(100);
				if (crit < 20) {
					hp -= (bullet.damage * 2);
					if (hp <= 0)
						die();
					break;
				} else {
					hp -= bullet.damage;
					if (hp <= 0)
						die();
					break;
				}
			}
		} else {
			hp -= bullet.damage;
			if (hp <= 0)
				die();
		}
		this.viewable.update();
	}

	public abstract void cutInHalf();
}
